#pragma once

#include <stdio.h>

namespace decorator {
    
/// @brief 抽象组件 - 被装饰的接口基类
class AbstractComponent {
public:
    virtual ~AbstractComponent() {}
    virtual void Request() = 0;
};

/// @brief 具体组件 - 被装饰的接口派生类
class ConcreteComponent : public AbstractComponent {
public:
    virtual void Request() {
        printf("this is ConcreteComponent::Request!\n");
    }
};

/// @brief 抽象装饰
class AbstractDecorator : public AbstractComponent {
public:
    AbstractDecorator(AbstractComponent* comp) : comp_(comp) {}

    virtual void Request() {
        if (comp_) comp_->Request();
    }

private:
    AbstractComponent* comp_;
};

/// @brief 具体装饰
class ConcreteDecoratorA : public AbstractDecorator {
public:
    ConcreteDecoratorA(AbstractComponent* comp) : AbstractDecorator(comp) {}

    virtual void Request() {
        PreRequest();
        AbstractDecorator::Request();
        PostRequest();
    }

protected:
    void PreRequest() {
        printf("ConcreteDecoratorA::PreRequest!\n");
    }
    void PostRequest() {
        printf("ConcreteDecoratorA::PostRequest!\n");
    }
};

} // namespace decorator

void Test_09_decorator_impl_1() {
    printf("-------------------- %s --------------------\n", __FUNCTION__);
    decorator::AbstractComponent* ptr_comp = new decorator::ConcreteComponent();
    ptr_comp->Request();    // 原有组件该有的功能不变

    // 对现有组件的功能进行扩展
    decorator::AbstractDecorator* ptr_decorator = new decorator::ConcreteDecoratorA(ptr_comp);
    ptr_decorator->Request();
    
    delete ptr_decorator;
    delete ptr_comp;
}

// -------------------- Test_09_decorator_impl_1 --------------------
// this is ConcreteComponent::Request!
// ConcreteDecoratorA::PreRequest!
// this is ConcreteComponent::Request!
// ConcreteDecoratorA::PostRequest!